package flib;

import java.io.File;
import java.util.Collection;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.Vector;

import blobDetector.Blob;
import blobDetector.BlobCell;
import blobDetector.BlobDetector;
import peasy.PeasyCam;
import processing.core.PApplet;
import processing.core.PImage;
import simpleGeom.HasPos2D;
import simpleGeom.Polygon2D;
import simpleGeom.PolygonSimplification;
import simpleGui.FileHelper;
import simpleGui.PCam2DGraphics;

public class ImageCleanerApplet extends PApplet {
	PImage image;
	ImageCleaner cleaner;
	BlobDetector bD;
	PeasyCam cam;
	String path="/Users/administrator/projekte/Doktor/References/PDF/Das Grundrisswerk scan/data/";
	String pathInput="img/";
	String pathOutput="imgEdit/";
	Vector<File>files=new Vector<File>();
	int indexFile=89;
	boolean doSave;
	boolean doLoad;
	PCam2DGraphics cam2d;
	FlibGraph graph=new FlibGraph();

	
	FloorplanLoader2D loader;
	TreeMap<String,FlibBuilding>buildings=new TreeMap<String,FlibBuilding>();
	
	public void setup() {
		setup2d();
		files=FileHelper.getFilesFromFolder(path+pathInput,".png");

		
		//image = loadImage("/Users/administrator/projekte/Doktor/References/PDF/Das Grundrisswerk scan/data/img/b1p020f53n315Layer 1.png");
		//image = loadImage("/Users/administrator/projekte/Doktor/References/PDF/Das Grundrisswerk scan/data/img/b1p101f499n180Layer 2.png");
		loadImage(indexFile);
		processImage(image);
		//image = loadImage("/Users/administrator/projekte/Doktor/References/PDF/Das Grundrisswerk scan/data/img/b1p099f490layer 1.png");
		
		
		loader=new FloorplanLoader2D(new File("/Users/administrator/Documents/workspace/FrameWork1308P2/flibConfig.xml"));
		//buildings=loader.loadBuildings("/Users/administrator/projekte/Doktor/References/PDF/Das Grundrisswerk scan/data/obj/");
		//building=loadBuilding(0);
	}
	public void setup3d(){
		size(1000, 700,P3D);
		cam = new PeasyCam(this,200,200,0, 1000);
	}
public void setup2d(){
	size(1400, 900);
	cam2d = new PCam2DGraphics(this);
}
	FlibBuilding building;
	public FlibBuilding loadBuilding(int index){
		println("load building");
		Vector<FlibBuilding>allBuildings=new Vector<FlibBuilding>();
		Collection<FlibBuilding>c= buildings.values();
		for ( Iterator it = c.iterator(); it.hasNext(); )
		{
			FlibBuilding b =   (FlibBuilding)   it.next();
			allBuildings.add(b);
		}
		FlibBuilding cBuilding=allBuildings.get(index);
		for (int i=0;i<cBuilding.levels.size();i++){
			FlibLevel level=cBuilding.levels.get(i);
			String name=level.filename;
			println("name: "+name);
			println("index: "+index);
			name=name.replace(".obj", ".png");
			PImage img=this.loadImage(path+"img/"+name);
			level.image=img;
			BlobDetector bd=processImage(img);
			for (int ii = 0; ii < bd.blobs.size(); ii++) {
				Blob blob = bd.blobs.get(ii);
				float[] xCors = new float[blob.getBorders().size()];
				float[] yCors = new float[blob.getBorders().size()];
				boolean[] inside = new boolean[xCors.length];
				for (int j = 0; j < blob.getBorders().size(); j++) {
					BlobCell bc = blob.getBorders().get(j);
					xCors[j] = bc.getX();
					yCors[j] = bc.getY();
				}
				PolygonSimplification.simplify(xCors, yCors,3, inside);
				Polygon2D poly=new Polygon2D();
				for (int j = 0; j < blob.getBorders().size(); j++) {
					BlobCell bc = blob.getBorders().get(j);
					if (inside[j]) {
						poly.addPt(bc.getX(), bc.getY());
					}
				}
				level.outlines.add(poly);
			}
		}
		println("building loaded");
		return cBuilding;
	}
	public void loadImage(int i){
		
		File file=files.get(i);
		image=loadImage(file.getAbsolutePath());
		cam2d.setBounds(0, 0, image.width, image.height);
		println("index: "+i+" file: "+file.getName());
	}
	
	public BlobDetector processImage(PImage image){
		graph=new FlibGraph();
		cleaner = new ImageCleaner(this, image);
		cleaner.contrast(100);
		cleaner.selectColor(255);
		cleaner.offsetSelection(5);
		cleaner.fillSelection(255);
		cleaner.invertSelection();
		cleaner.offsetSelection(7);
		cleaner.fillSelection(0);
		cleaner.invertSelection();
		cleaner.offsetSelection(2);
		cleaner.fillSelection(255);
		cleaner.selectColor(0);
		
		
		/*
		 * cleaner.offsetSelection(60); cleaner.fillSelection(0);
		 * cleaner.invertSelection(); cleaner.offsetSelection(50);
		 * cleaner.fillSelection(255);
		 */
		

		bD = new BlobDetector(image.width, image.height);
		bD.setValues(cleaner.values);
		bD.calculateBlobsFloat(10);
		Vector<Blob> blobs = bD.getBlobs();
		cleaner.removeSelection();
		for (int i = 0; i < blobs.size(); i++) {
			Blob blob = blobs.get(i);
			if (blob.getArea() < 1000&&blob.getArea()>0) {
				boolean[][]matrix=blob.containsMatrix();
				for (int x=blob.getMinX();x<=blob.getMaxX();x++){
					for (int y=blob.getMinY();y<=blob.getMaxY();y++){
						if (matrix[x-blob.getMinX()][y-blob.getMinY()]){
							cleaner.selection[y*cleaner.nX+x] = true;
						}
					}
				}
			}
		}
		cleaner.fillSelection(255);
		cleaner.renderResult();
		bD.setValues(cleaner.values);
		bD.calculateBlobsFloat(10);
		blobs = bD.getBlobs();
		for (int i = 0; i < blobs.size(); i++) {
		
			Blob blob = blobs.get(i);
			float[] xCors = new float[blob.getBorders().size()];
			float[] yCors = new float[blob.getBorders().size()];
			for (int j = 0; j < blob.getBorders().size(); j++) {
				BlobCell c = blob.getBorders().get(j);
				xCors[j]=c.getX();
				yCors[j]=c.getY();
			}
			
			boolean[] inside = new boolean[xCors.length];
			PolygonSimplification.simplify(xCors, yCors,2, inside);
			
			int nIn = 0;
			Vector<FlibHENode>nodes=new Vector<FlibHENode>();
			if (PolygonSimplification.getArea(xCors, yCors) !=0) {
				for (int j = 0; j < blob.getBorders().size(); j++) {
					if (inside[j]) {
					BlobCell c = blob.getBorders().get(j);
						nodes.add(graph.addNode(c.getX(), c.getY()));
					}
				}
			}
			for (int j=0;j<nodes.size();j++){
				FlibHENode n1=nodes.get(j);
				int j2=(j+1)%nodes.size();
				FlibHENode n2=nodes.get(j2);
				FlibWall wall=graph.addWall(n1, n2);
				wall.hEdge.attach();
				println(graph.walls.size());
			}
			
			
		}
		graph.createRoomsInner();
		println("nRooms: "+graph.rooms.size());
		return bD;
	}
	float levelH=270;
	public void draw3D(FlibBuilding building){
		lights();
		fill(0,255,0,100);
		noStroke();
		for (int i=0;i<building.levels.size();i++){
			FlibLevel level=building.levels.get(i);
			pushMatrix();
			translate(0,0,levelH*i);
			Vector<Polygon2D>outlines=level.outlines;
			level.display2D(g);
			pushMatrix();
			translate(0,0,20);
			level.display2D(g);
			
			popMatrix();
			//image(level.image,0,0);
			for (int ii=0;ii<outlines.size();ii++){
				Polygon2D p2d=outlines.get(ii);
				beginShape(QUAD_STRIP);
				for (int iii=0;iii<p2d.getNPts();iii++){
					HasPos2D p=p2d.get(iii);
					vertex(p.getX(),p.getY(),0);
					vertex(p.getX(),p.getY(),levelH);
				}
				endShape();
			}
			translate(0,0,levelH);
			level.display2D(g);
			popMatrix();
		}
	}
	
	
	public void draw2D(){
		if (doLoad){
			loadImage(indexFile);
			processImage(image);
			doLoad=false;
		}
		cam2d.useCam(g);
		background(100);
		scale(1);
		image(image,0,0,image.width,image.height);
		Vector<Blob> blobs = bD.getBlobs();
		rectMode(CENTER);
		g.stroke(255,0,0);
		g.fill(255,0,0,50);
		for (int i=0;i<graph.rooms.size();i++){
			FlibFace face=graph.rooms.get(i);
		}
		graph.display2D(g);
	}
	
	public void draw() {
		draw2D();
	}
	
	public void keyPressed(){
		if (key=='i'){
			indexFile++;
			indexFile=indexFile%files.size();
			doLoad=true;
		}
		if (key=='s'){
			doSave=true;
		}
	}
}
